package edu.northwestern.cbits.purple_robot_manager.probes.builtin;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.os.Bundle;
import android.os.PowerManager.WakeLock;
import android.preference.CheckBoxPreference;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import edu.northwestern.cbits.purple_robot_manager.R;
import edu.northwestern.cbits.purple_robot_manager.activities.settings.FlexibleListPreference;
import edu.northwestern.cbits.purple_robot_manager.logging.LogManager;
import edu.northwestern.cbits.purple_robot_manager.probes.Probe;
import edu.northwestern.cbits.purple_robot_manager.util.WakeLockManager;
public abstract class ContinuousProbe extends Probe
{
public static final String EVENT_TIMESTAMP = "EVENT_TIMESTAMP";
public static final String SENSOR_TIMESTAMP = "SENSOR_TIMESTAMP";
public static final String NORMALIZED_TIMESTAMP = "NORMALIZED_TIMESTAMP";
public static final String SENSOR_MAXIMUM_RANGE = "MAXIMUM_RANGE";
public static final String SENSOR_NAME = "NAME";
public static final String SENSOR_POWER = "POWER";
public static final String SENSOR_TYPE = "TYPE";
public static final String SENSOR_VENDOR = "VENDOR";
public static final String SENSOR_VERSION = "VERSION";
public static final String SENSOR_RESOLUTION = "RESOLUTION";
public static final String BUNDLE_SENSOR = "SENSOR";
public static final String SENSOR_ACCURACY = "ACCURACY";
public static final String PROBE_THRESHOLD = "threshold";
protected static final boolean DEFAULT_ENABLED = false;
public static final String DEFAULT_FREQUENCY = "0";
public static final String USE_THREAD = "use_thread";
public static final boolean DEFAULT_USE_HANDLER = true;
private static final String PROBE_WAKELOCK = "wakelock";
private WakeLock _wakeLock = null;
private int _wakeLockLevel = -1;
protected Context _context = null;
private boolean _lastEnableResult = false;
private long _lastEnableCheck = 0;
@Override
public void enable(Context context)
{
String key = this.getPreferenceKey();
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putBoolean("config_probe_" + key + "_enabled", true);
e.commit();
}
@Override
public void disable(Context context)
{
String key = this.getPreferenceKey();
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putBoolean("config_probe_" + key + "_enabled", false);
e.commit();
}
protected boolean shouldProcessEvent(SensorEvent event)
{
long now = System.currentTimeMillis();
if (now - this._lastEnableCheck > 5000)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this._context);
// TODO: Replace string keys below...
String key = this.getPreferenceKey();
this._lastEnableResult = prefs.getBoolean("config_probes_enabled", false);
if (this._lastEnableResult)
this._lastEnableResult = prefs.getBoolean("config_probe_" + key + "_enabled", ContinuousProbe.DEFAULT_ENABLED);
this._lastEnableCheck = now;
}
return this._lastEnableResult;
}
public PreferenceScreen preferenceScreen(Context context, PreferenceManager manager, boolean includePreferences)
{
if (includePreferences)
return this.preferenceScreen(context, manager);
return super.preferenceScreen(context, manager);
}
public PreferenceScreen preferenceScreen(Context context, PreferenceManager manager)
{
PreferenceScreen screen = super.preferenceScreen(context, manager);
screen.setTitle(this.title(context));
screen.setSummary(this.summary(context));
String key = this.getPreferenceKey();
CheckBoxPreference enabled = new CheckBoxPreference(context);
enabled.setTitle(R.string.title_enable_probe);
enabled.setKey("config_probe_" + key + "_enabled");
enabled.setDefaultValue(ContinuousProbe.DEFAULT_ENABLED);
screen.addPreference(enabled);
int values = this.getResourceFrequencyValues();
int labels = this.getResourceFrequencyLabels();
if (values != -1 && labels != -1) {
FlexibleListPreference duration = new FlexibleListPreference(context);
duration.setKey("config_probe_" + key + "_frequency");
duration.setEntryValues(values);
duration.setEntries(labels);
duration.setTitle(R.string.probe_frequency_label);
duration.setDefaultValue(ContinuousProbe.DEFAULT_FREQUENCY);
screen.addPreference(duration);
FlexibleListPreference wakelock = new FlexibleListPreference(context);
wakelock.setKey("config_probe_" + key + "_wakelock");
wakelock.setEntryValues(R.array.wakelock_values);
wakelock.setEntries(R.array.wakelock_labels);
wakelock.setTitle(R.string.probe_wakelock_title);
wakelock.setSummary(R.string.probe_wakelock_summary);
wakelock.setDefaultValue("-1");
screen.addPreference(wakelock);
}
return screen;
}
@Override
public Map<String, Object> configuration(Context context)
{
Map<String, Object> map = super.configuration(context);
map.put(Probe.PROBE_FREQUENCY, this.getFrequency());
map.put(ContinuousProbe.PROBE_THRESHOLD, this.getThreshold());
JSONObject settings = this.fetchSettings(context);
if (settings.has(ContinuousProbe.USE_THREAD))
map.put(ContinuousProbe.USE_THREAD, this.getUsesThread());
map.put(ContinuousProbe.PROBE_WAKELOCK, this.getWakelock());
return map;
}
private int getWakelock()
{
String key = this.getPreferenceKey();
SharedPreferences prefs = Probe.getPreferences(this._context);
int lock = -1;
try
{
lock = Integer.parseInt(prefs.getString("config_probe_" + key + "_wakelock", "-1"));
}
catch (NumberFormatException e)
{
lock = (int) Float.parseFloat(prefs.getString("config_probe_" + key + "_wakelock", "-1"));
}
return lock;
}
protected abstract boolean getUsesThread();
protected abstract double getThreshold();
@Override
public void updateFromMap(Context context, Map<String, Object> params)
{
super.updateFromMap(context, params);
if (params.containsKey(Probe.PROBE_FREQUENCY))
{
Object frequency = params.get(Probe.PROBE_FREQUENCY);
if (frequency instanceof Long || frequency instanceof Integer)
{
String key = "config_probe_" + this.getPreferenceKey() + "_frequency";
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(key, frequency.toString());
e.commit();
}
if (frequency instanceof Double)
{
String key = "config_probe_" + this.getPreferenceKey() + "_frequency";
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(key, "" + ((Double) frequency).intValue());
e.commit();
}
else if (frequency instanceof String)
{
String key = "config_probe_" + this.getPreferenceKey() + "_frequency";
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(key, frequency.toString());
e.commit();
}
}
if (params.containsKey(ContinuousProbe.PROBE_THRESHOLD))
{
Object threshold = params.get(ContinuousProbe.PROBE_THRESHOLD);
if (threshold instanceof Long || threshold instanceof Integer)
{
String key = "config_probe_" + this.getPreferenceKey() + "_threshold";
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(key, "" + threshold);
e.commit();
}
if (threshold instanceof Double)
{
String key = "config_probe_" + this.getPreferenceKey() + "_threshold";
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(key, "" + threshold);
e.commit();
}
else if (threshold instanceof String)
{
String key = "config_probe_" + this.getPreferenceKey() + "_threshold";
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(key, "" + threshold);
e.commit();
}
}
if (params.containsKey(ContinuousProbe.PROBE_WAKELOCK))
{
Object wakelock = params.get(ContinuousProbe.PROBE_WAKELOCK);
if (wakelock instanceof Long || wakelock instanceof Integer)
{
String key = "config_probe_" + this.getPreferenceKey() + "_wakelock";
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(key, "" + wakelock);
e.commit();
}
if (wakelock instanceof Double)
{
String key = "config_probe_" + this.getPreferenceKey() + "_wakelock";
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(key, "" + wakelock);
e.commit();
}
else if (wakelock instanceof String)
{
String key = "config_probe_" + this.getPreferenceKey() + "_wakelock";
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(key, "" + wakelock);
e.commit();
}
}
}
@Override
public Bundle formattedBundle(Context context, Bundle bundle)
{
Bundle formatted = super.formattedBundle(context, bundle);
return formatted;
}
public int getResourceFrequencyLabels()
{
return R.array.probe_continuous_frequency_labels;
}
public int getResourceFrequencyValues()
{
return R.array.probe_continuous_frequency_values;
}
public abstract long getFrequency();
public abstract int getTitleResource();
public abstract int getSummaryResource();
protected abstract boolean passesThreshold(SensorEvent event);
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
}
@Override
public String title(Context context)
{
return context.getString(this.getTitleResource());
}
@Override
public String summary(Context context)
{
return context.getString(this.getSummaryResource());
}
@Override
@SuppressLint("Wakelock")
public boolean isEnabled(Context context)
{
boolean enabled = super.isEnabled(context);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String key = this.getPreferenceKey();
if (enabled)
enabled = prefs.getBoolean("config_probe_" + key + "_enabled", ContinuousProbe.DEFAULT_ENABLED);
int wakeLevel = (int) Float.parseFloat(prefs.getString("config_probe_" + key + "_wakelock", "-1"));
if (enabled)
{
if (wakeLevel != this._wakeLockLevel)
{
if (this._wakeLock != null)
{
WakeLockManager.getInstance(context).releaseWakeLock(this._wakeLock);
this._wakeLock = null;
}
this._wakeLockLevel = wakeLevel;
}
if (this._wakeLockLevel != -1 && this._wakeLock == null)
this._wakeLock = WakeLockManager.getInstance(context).requestWakeLock(this._wakeLockLevel, this.getClass().getCanonicalName());
}
else
{
if (this._wakeLock != null)
{
WakeLockManager.getInstance(context).releaseWakeLock(this._wakeLock);
this._wakeLock = null;
}
}
return enabled;
}
@Override
public JSONObject fetchSettings(Context context)
{
JSONObject settings = super.fetchSettings(context);
try
{
int frequencyValues = this.getResourceFrequencyValues();
if (frequencyValues != -1)
{
JSONObject frequency = new JSONObject();
frequency.put(Probe.PROBE_TYPE, Probe.PROBE_TYPE_LONG);
JSONArray values = new JSONArray();
String[] options = context.getResources().getStringArray(frequencyValues);
for (String option : options)
{
values.put(Long.parseLong(option));
}
frequency.put(Probe.PROBE_VALUES, values);
settings.put(Probe.PROBE_FREQUENCY, frequency);
}
int thresholdValues = this.getResourceThresholdValues();
if (thresholdValues != -1)
{
JSONObject threshold = new JSONObject();
threshold.put(Probe.PROBE_TYPE, Probe.PROBE_TYPE_DOUBLE);
JSONArray values = new JSONArray();
String[] options = context.getResources().getStringArray(thresholdValues);
for (String option : options)
{
values.put(Double.parseDouble(option));
}
threshold.put(Probe.PROBE_VALUES, values);
settings.put(ContinuousProbe.PROBE_THRESHOLD, threshold);
}
JSONObject wakelock = new JSONObject();
wakelock.put(Probe.PROBE_TYPE, Probe.PROBE_TYPE_LONG);
JSONArray values = new JSONArray();
String[] options = context.getResources().getStringArray(R.array.wakelock_values);
for (String option : options)
{
values.put(Double.parseDouble(option));
}
wakelock.put(Probe.PROBE_VALUES, values);
settings.put(ContinuousProbe.PROBE_WAKELOCK, wakelock);
}
catch (JSONException e)
{
LogManager.getInstance(context).logException(e);
}
return settings;
}
protected abstract int getResourceThresholdValues();
}